package cn.agiledata.bank.audit.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import cn.agiledata.bank.audit.exception.AuditException;
import cn.agiledata.bank.audit.logic.AuditLevel;
import cn.agiledata.bank.hibernateBean.AuditGroup;
import cn.agiledata.bank.hibernateBean.AuditStep;

public final class AuditStepServiceImpl implements AuditStepService {
    public AuditStep getAuditStepByLevel(AuditStep[] auditSteps, int level) {
        for (int i = 0; i < auditSteps.length; i++) {
            if (auditSteps[i].getLevel() == level)
                return auditSteps[i];
        }
        return null;
    }

    public AuditStep[] appendAuditStep(Long auditorId, String name,
            AuditGroup auditGroup, AuditStep[] auditSteps)
            throws AuditException {
        AuditStep auditStep = new AuditStep();
        AuditLevel auditLevel = AuditLevel.LEVEL_PRIMARY;
        if (auditSteps == null)
            auditSteps = new AuditStep[0];
        if (auditSteps.length > 0) {
            int maxLevel = auditSteps[auditSteps.length - 1].getLevel();
            auditLevel = AuditLevel.getAuditLevel(maxLevel).nextAuditLevel();
        }
        checkAuditStep(auditSteps, auditStep.getId(), auditGroup, name);
        auditStep.setLevel(auditLevel.getValue());
        auditStep.setName(name);
        auditStep.setAuditGroup(auditGroup);
        auditStep.setUpdateUser(auditorId.toString());
        auditStep.setUpdateTime(new Date());
        auditStep.setCreateUser(auditStep.getUpdateUser());
        auditStep.setCreateTime(auditStep.getUpdateTime());
        AuditStep[] newAuditSteps = new AuditStep[auditSteps.length + 1];
        System.arraycopy(auditSteps, 0, newAuditSteps, 0, auditSteps.length);
        newAuditSteps[auditSteps.length] = auditStep;
        return newAuditSteps;
    }

    public AuditStep[] removeAuditStep(AuditStep[] auditSteps, int level) {
        if (auditSteps == null || auditSteps.length == 0)
            return new AuditStep[0];
        List newAuditSteps = new ArrayList();
        int removedIndex = -1;
        for (int i = 0; i < auditSteps.length; i++) {
            if (auditSteps[i].getLevel() == level) {
                removedIndex = i;
            } else {
                if (removedIndex >= 0 && removedIndex < i) {
                    AuditStep preAuditStep = i == 1 ? null
                            : (AuditStep) newAuditSteps.get(i - 2);
                    AuditLevel auditLevel = preAuditStep == null ? AuditLevel.LEVEL_PRIMARY
                            : AuditLevel.getAuditLevel(preAuditStep.getLevel())
                                    .nextAuditLevel();
                    auditSteps[i].setLevel(auditLevel.getValue());
                }
                newAuditSteps.add(auditSteps[i]);
            }
        }
        return (AuditStep[]) newAuditSteps.toArray(new AuditStep[0]);
    }

    public void amendAuditStep(Long auditorId, String name,
            AuditGroup auditGroup, AuditStep[] auditSteps, int level)
            throws AuditException {
        AuditStep auditStep = getAuditStepByLevel(auditSteps, level);
        if (auditStep != null) {
            checkAuditStep(auditSteps, auditStep.getId(), auditGroup, name);
            auditStep.setName(name);
            auditStep.setAuditGroup(auditGroup);
            auditStep.setUpdateUser(auditorId.toString());
            auditStep.setUpdateTime(new Date());
        }
    }

    private void checkAuditStep(AuditStep[] auditSteps, Long auditStepId,
            AuditGroup auditGroup, String name) throws AuditException {
        for (int i = 0; i < auditSteps.length; i++) {
            if (auditSteps[i].getName().equals(name)) {
                if ((auditSteps[i].getId() == null && auditStepId == null)
                        || (auditSteps[i].getId() != null && !auditSteps[i]
                                .getId().equals(auditStepId)))
                    throw AuditException.AUDIT_STEP_NOT_UNIQUE_NAME;
            }
            if (auditSteps[i].getAuditGroup().getId()
                    .equals(auditGroup.getId())) {
                if ((auditSteps[i].getId() == null && auditStepId == null)
                        || (auditSteps[i].getId() != null && !auditSteps[i]
                                .getId().equals(auditStepId)))
                    throw AuditException.AUDIT_STEP_NOT_UNIQUE_AUDIT_GROUP;// 不允许一个审核组审核多个审核步骤
            }
        }
    }

}
